package com.ns.sbs.oauth.redis4console;

import com.ns.core.utils.sg.ResultError;
import com.ns.core.vo.mp.CustomMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.text.Collator;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * redis 控制台相关操作 util
 *
 * @author lw
 */
@Component
public class RedisConsoleUtil {


    static String dbN;

    /**
     * 最大加载数量
     */
    static Long loadMax = 10000L;

    /**
     * string专用
     */
    static StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplates, @Value("${spring.data.redis.database}") String dbN) {
        RedisConsoleUtil.stringRedisTemplate = stringRedisTemplates;
        RedisConsoleUtil.dbN = dbN;
    }


    /**
     * 获取reids信息
     */
    public static CustomMap getInfo() {
        // 加载所有信息
        Properties info = stringRedisTemplate.getRequiredConnectionFactory().getConnection().info();
        CustomMap map = new CustomMap();
        assert info != null;
        for (String key : info.stringPropertyNames()) {
            map.put(key, info.getProperty(key));
        }

        // 加载所有信息
        CustomMap so = new CustomMap();
        // key 总数
        so.set("keys_count", getKeyCount(map));
        // 被命中个数
        so.set("keyspace_hits", map.get("keyspace_hits"));
        // 已经占用内存数量
        so.set("used_memory_human", map.get("used_memory_human"));
        // 内存消耗峰值
        so.set("used_memory_peak_human", map.get("used_memory_peak_human"));
        // redis 已经启动的秒数
        so.set("uptime_in_seconds", map.get("uptime_in_seconds"));
        // 是否已经超过了最大值
        so.set("isGtMax", so.getLong("keys_count") > loadMax);

        return so;
    }


    /**
     * 获取keys列表
     */
    public static List<String> getKeys(String k) {

        // 如果为空，则查询所有
        if (k == null || k.isEmpty()) {
            k = "*";
        }

        // 检查是否超过上限
        Set<String> keysSet = stringRedisTemplate.keys(k);
        ResultError.throwBy(keysSet.size() > loadMax, 501, "key值数量超" + loadMax + "<br/>为性能考虑无法返回数据，请更换筛选条件");

        // 排序
        List<String> keys = new ArrayList<String>(keysSet);

        // 按照字典排序
        keys.sort((o1, o2) -> {
            Comparator<Object> com = Collator.getInstance(Locale.CHINA);
            return com.compare(o1, o2);

        });

        return keys;
    }


    /**
     * 获取单个的详情
     */
    public static CustomMap getByKey(String key) {
        // 键值
        String value = null;
        try {
            value = stringRedisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            value = "未能成功获取：" + e.getMessage();
        }

        // 过期时间
        Long expire = stringRedisTemplate.getExpire(key);

        return new CustomMap()
                .set("key", key)
                .set("value", value)
                .set("ttl", expire);
    }

    /**
     * 写入一个值
     */
    public static void setBySeconds(String key, String value, Long timeout) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 删除一个值
     */
    public static void del(String key) {
        stringRedisTemplate.delete(key);
    }

    /**
     * 修改一个值的value
     */
    public static void updateValue(String key, String value) {
        Long expire = stringRedisTemplate.getExpire(key);
        // 1 = 永久
        if (expire == -1) {
            stringRedisTemplate.opsForValue().set(key, value);
            return;
        }
        // -2 = 无此键
        if (expire == -2) {
            return;
        }
        stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
    }

    /**
     * 修改一个值的ttl
     */
    public static void updateTtl(String key, Long ttl) {
        if (ttl < 0) {
            // 注意此处可能因为序列化格式的不同，导致数据修改为无效数据
            String value = stringRedisTemplate.opsForValue().get(key);
            stringRedisTemplate.opsForValue().set(key, value);
            return;
        }
        stringRedisTemplate.expire(key, ttl, TimeUnit.SECONDS);
    }

    /**
     * 根据info获取当前 key总数
     */
    private static Long getKeyCount(CustomMap map) {
        Long keysCount = 0L;
        try {
            // 计算 key 总数
            String dbName = dbN;
            String dbInfo = map.getString("db" + dbName);
            if (dbInfo != null) {
                String[] arr = dbInfo.split(",");
                for (String item : arr) {
                    String[] arr2 = item.split("=");
                    if ("keys".equals(arr2[0])) {
                        keysCount = Long.valueOf(arr2[1]);
                    }
                }
            }
        } catch (Exception e) {
            throw new ResultError("获取REDIS-KEYS总数出错！");
        }
        return keysCount;
    }


}
